#include "ctcpdownload.h"


CTcpDownload::CTcpDownload():
    m_nUserID(-1),
    m_nSock(-1),
    m_cb(NULL),
    m_bcancle(true)
{
    m_pBufSend = new char[32];
    m_pBufRecv = new char[2048];
    m_pbuf264  = new char[1024*1024];
}

CTcpDownload::~CTcpDownload()
{
    if(m_pBufSend != NULL)
    {
        delete [] m_pBufSend;
        m_pBufSend = NULL;
    }
    if(m_pBufRecv != NULL)
    {
        delete [] m_pBufRecv;
        m_pBufRecv = NULL;
    }
    if(m_pbuf264 != NULL)
    {
        delete [] m_pbuf264;
        m_pbuf264 = NULL;
    }
}

int CTcpDownload::OpenDownload(int uerid, TCPDownLoadCB cb, const char *ip, int port)
{
     m_nUserID = uerid;
     m_cb     = cb;
     m_bcancle = false;

    *(unsigned short*)(m_pBufSend) = 11;
    *(int*)(m_pBufSend+2) = uerid;
    *(m_pBufSend+6) = 0x00;
    *(int*)(m_pBufSend+7) = 0x0010 ;

     m_nSock = socket(AF_INET, SOCK_STREAM, 0);
     if(m_nSock < 0)
     {

        // __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "create socket error errorcode:%d",errno);
         return -1;
     }
     sockaddr_in addr;
     memset(&addr, 0, sizeof(addr));
     addr.sin_family = AF_INET;
     addr.sin_port = htons(port);
     addr.sin_addr.s_addr = inet_addr(ip);

     if(connect(m_nSock,(sockaddr*)&addr, sizeof(addr)) < 0)
     {
       // __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "connect error errorcode:%d",errno);
        return -1;
     }

     struct timeval timeoutrecv;
     timeoutrecv.tv_sec  = 3;
     timeoutrecv.tv_usec = 0;
     if(setsockopt(m_nSock,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeoutrecv.tv_sec,sizeof(struct timeval)) < 0)
     {
         //__android_log_print(ANDROID_LOG_INFO, "JNIMsg", "setsockopt error errorcode:%d",errno);
         return -1;
     }

     struct timeval timeoutsend;
     timeoutsend.tv_sec  = 3;
     timeoutsend.tv_usec = 0;
     if(setsockopt(m_nSock,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeoutsend.tv_sec,sizeof(struct timeval)) < 0)
     {
        // __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "setsockopt error errorcode:%d",errno);
         return -1;
     }

     if(sendn(m_pBufSend, 11) < 0)
     {
         return -1;
     }
    //send(m_nSock, m_pBufSend, 11, 0);


     return 0;
}

int CTcpDownload::CloseDownload()
{
    m_bcancle = true;
    if(m_nSock != -1)
    {
        close(m_nSock);
        m_nSock = -1;
    }

    return 0;
}

int CTcpDownload::Download()
{

   int iret = 0;
   time(&m_tmlast);


   if(sendn(m_pBufSend, 11) < 0)
   {
       return -1;
   }

   int  framesize = 0;

   while(!m_bcancle)
   {
       iret = recvn(m_pBufRecv, 2);
       if(iret < 0)
       {
           return -1;   //something error
       }
       unsigned short  len = *(unsigned short*)m_pBufRecv;
       if(len > 1500)
       {
           return -1;  //something error
       }
       iret = recvn(m_pBufRecv+2, len-2);
       if(iret < 0)
       {
            return -1;   //something error
       }

       if(m_pBufRecv[6] == (char)0xf1 )
       {
    	   static unsigned short lastindex = 0;
    	   unsigned short index = *(unsigned short*)(m_pBufRecv+7);
    	   if(index-lastindex != 1)
    	   {
        //	   __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "lastindex:%d, index:%d",lastindex, index);
    	   }
    	   lastindex = index;


           if(m_pBufRecv[9] ==  (char)0x01)
           {
               framesize = 0;
               memcpy(m_pbuf264+framesize,m_pBufRecv+10, len-10 );
               framesize +=  len-10;

           }
           else if(m_pBufRecv[9] ==  (char)0x03)
           {
               memcpy(m_pbuf264+framesize,m_pBufRecv+10, len-10 );
               framesize +=  len-10;

               if(m_cb != NULL)
               {
                   m_cb(m_pbuf264, framesize);
               }
               framesize = 0;
           }
           else
           {
               if(framesize > 1024*1024)
               {
                  framesize = 0;
               }
               memcpy(m_pbuf264+framesize,m_pBufRecv+10, len-10 );
               framesize +=  len-10;
           }
       }


   }

    return 0;
}
int CTcpDownload::recvn(char* buf, int size)
{
    int len = 0;
    int ret = 0;

    while(len < size)
    {
    	// __android_log_print(ANDROID_LOG_INFO, "JNIMsg","id %d download", m_nUserID);

    	 time_t tm ;
    	 time(&tm);
    	 if(tm-m_tmlast > 3)
    	 {
    		 sendn(m_pBufSend, 11);
    	     //send(m_nSock, m_pBufSend, 11, 0);
    	     m_tmlast = tm;
    //	     __android_log_print(ANDROID_LOG_INFO, "JNIMsg","id %d beatheart", m_nUserID);
    	 }

    	// __android_log_print(ANDROID_LOG_INFO, "JNIMsg","id %d tmnow %ld tmlast %ld", m_nUserID, tm, m_tmlast);



        ret = recv(m_nSock, buf+len , size-len ,0 );
        if (ret ==-1)
        {
            if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
            {
                continue;
            }
            else
            {
                return -1;
            }
        }
        if(ret == 0)
        {
            return -1;
        }
        len += ret;
    }
    return len;
}

int CTcpDownload::sendn(char* data, int len)
{
    int nsend = 0;
    int ret = 0;
    while(nsend < len)
    {
        ret = send(m_nSock, data+nsend , len-nsend ,0 );
        if (ret ==-1)
        {
            if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
            {
                continue;
            }
            else
            {
                return -1;
            }
        }
        if(ret == 0)
        {
            return -1;
        }
        nsend += ret;
    }
    return nsend;
}
